import numpy as np
from datetime import datetime, timedelta


class LoanUnExtensionV2():

    def __init__(self, loan_un_base_v2):
        self.acq_channel = loan_un_base_v2.acq_channel
        self.product_code = loan_un_base_v2.product_code
        self.order_apply_time = loan_un_base_v2.order_apply_time
        self.order_apply_time_datetime = loan_un_base_v2.order_apply_time_datetime
        self.order_apply_date = loan_un_base_v2.order_apply_date
        self.installments_data_df = loan_un_base_v2.installments_data_df
        self.contract_data_df = loan_un_base_v2.contract_data_df

    def gen_features(self):
        feature_dict = {}
        day_list = [1, 3, 7, 15, 30, 60, 90, 180, 360]
        cnt_list = [1, 3, 7, 15, 30]
        order_type_list = [('acq_channel', self.acq_channel, True), ('acq_channel', self.acq_channel, False), ('product_code', self.product_code, True), ('product_code', self.product_code, False), 'all']
        time_type_list = [(0, 5), (6, 12), (13, 18), (19, 23)]
        day_type_list = [('is_workday', 1), ('is_workday', 0), ('is_holiday', 1), ('is_holiday', 0)]

        for day in day_list:
            tmp1_installments_data_df = self.installments_data_df[self.installments_data_df['day_interval'] <= day]
            for order_type in order_type_list:
                if order_type == 'all':
                    tmp2_installments_data_df = tmp1_installments_data_df
                    tmp_contract_data_df = self.contract_data_df[self.contract_data_df['app_order_id'].isin(tmp2_installments_data_df['app_order_id'])]
                    suffix = f'd{day}_all'
                    self.__gen_extension_feature(tmp2_installments_data_df,tmp_contract_data_df,suffix,feature_dict)
                else:
                    tmp2_installments_data_df = tmp1_installments_data_df[(tmp1_installments_data_df[order_type[0]] == order_type[1]) == order_type[2]]
                    tmp_contract_data_df = self.contract_data_df[self.contract_data_df['app_order_id'].isin(tmp2_installments_data_df['app_order_id'])]
                    suffix = f'd{day}_{order_type[0].split("_")[0]}{int(order_type[2])}'
                    self.__gen_extension_feature(tmp2_installments_data_df,tmp_contract_data_df,suffix,feature_dict)

            for time_type in time_type_list:
                tmp2_installments_data_df = tmp1_installments_data_df[(tmp1_installments_data_df['create_time_hour'] >= time_type[0]) & (tmp1_installments_data_df['create_time_hour'] <= time_type[1])]
                tmp_contract_data_df = self.contract_data_df[self.contract_data_df['app_order_id'].isin(tmp2_installments_data_df['app_order_id'])]
                suffix = f'd{day}_time{time_type[0]}-{time_type[1]}'
                self.__gen_extension_feature(tmp2_installments_data_df,tmp_contract_data_df,suffix,feature_dict)

            for day_type in day_type_list:
                tmp2_installments_data_df = tmp1_installments_data_df[tmp1_installments_data_df[day_type[0]] == day_type[1]]
                tmp_contract_data_df = self.contract_data_df[self.contract_data_df['app_order_id'].isin(tmp2_installments_data_df['app_order_id'])]
                suffix = f'd{day}_{day_type[0].split("_")[1]}{day_type[1]}'
                self.__gen_extension_feature(tmp2_installments_data_df,tmp_contract_data_df,suffix,feature_dict)

        app_order_id_sort = self.installments_data_df.sort_values('create_time', ascending=False)['app_order_id'].drop_duplicates()
        for cnt in cnt_list:
            tmp1_installments_data_df = self.installments_data_df[self.installments_data_df['app_order_id'].isin(app_order_id_sort.iloc[:cnt])]
            for order_type in order_type_list:
                if order_type == 'all':
                    tmp2_installments_data_df = tmp1_installments_data_df
                    tmp_contract_data_df = self.contract_data_df[self.contract_data_df['app_order_id'].isin(tmp2_installments_data_df['app_order_id'])]
                    suffix = f'cnt{cnt}_all'
                    self.__gen_extension_feature(tmp2_installments_data_df,tmp_contract_data_df,suffix,feature_dict)
                else:
                    tmp2_installments_data_df = tmp1_installments_data_df[(tmp1_installments_data_df[order_type[0]] == order_type[1]) == order_type[2]]
                    tmp_contract_data_df = self.contract_data_df[self.contract_data_df['app_order_id'].isin(tmp2_installments_data_df['app_order_id'])]
                    suffix = f'cnt{cnt}_{order_type[0].split("_")[0]}{int(order_type[2])}'
                    self.__gen_extension_feature(tmp2_installments_data_df, tmp_contract_data_df,suffix,feature_dict)

            for time_type in time_type_list:
                tmp2_installments_data_df = tmp1_installments_data_df[(tmp1_installments_data_df['create_time_hour'] >= time_type[0]) & (tmp1_installments_data_df['create_time_hour'] <= time_type[1])]
                tmp_contract_data_df = self.contract_data_df[self.contract_data_df['app_order_id'].isin(tmp2_installments_data_df['app_order_id'])]
                suffix = f'cnt{cnt}_time{time_type[0]}-{time_type[1]}'
                self.__gen_extension_feature(tmp2_installments_data_df, tmp_contract_data_df,suffix,feature_dict)

            for day_type in day_type_list:
                tmp2_installments_data_df = tmp1_installments_data_df[tmp1_installments_data_df[day_type[0]] == day_type[1]]
                tmp_contract_data_df = self.contract_data_df[self.contract_data_df['app_order_id'].isin(tmp2_installments_data_df['app_order_id'])]
                suffix = f'cnt{cnt}_{day_type[0].split("_")[1]}{day_type[1]}'
                self.__gen_extension_feature(tmp2_installments_data_df, tmp_contract_data_df,suffix,feature_dict)

        for key, value in feature_dict.items():
            feature_dict[key] = float(value) if not np.isnan(value) else -999.0

        return feature_dict

    def __gen_extension_feature(self, installments_data_df, contract_data_df,suffix,feature_dict):
        # 展期订单 统计
        order_statis_df = installments_data_df.groupby('app_order_id').agg({'app_order_id': 'count'}).rename(columns={'app_order_id': 'order_cnt'}).reset_index()
        extension_order_statis_df = order_statis_df[order_statis_df['order_cnt'] > 1]

        extension_order_num = extension_order_statis_df['app_order_id'].nunique()
        extension_extorder_num = extension_order_statis_df['order_cnt'].sum()

        # 合同按时间排序
        contract_data_df_sort = contract_data_df.sort_values('activation_time').reset_index(drop=True)
        # 展期合同
        extension_con_data_df = contract_data_df_sort[contract_data_df_sort['app_order_id'].isin(extension_order_statis_df['app_order_id'])]
        # 展期结清合同
        extension_repay_con_df = extension_con_data_df[extension_con_data_df['status'] == 6]

        extension_repay_con_num = extension_repay_con_df['app_order_id'].nunique()

        if not extension_con_data_df.empty:
            # 第一笔 展期合同
            extension_first_con_data_df = extension_con_data_df.head(1)
            extension_first_con_rank = extension_first_con_data_df.index[0] + 1
            extension_first_con_data_series = extension_first_con_data_df.iloc[0]
            extension_first_con_hour_diff = (datetime.strptime(extension_first_con_data_series['activation_time'], "%Y-%m-%d %H:%M:%S") - self.order_apply_time_datetime).total_seconds() / 3600
            extension_first_con_data_isrepay = 1 if extension_first_con_data_series['settlement_time'] else 0
            extension_first_con_data_ext_cnt = extension_order_statis_df.loc[extension_order_statis_df['app_order_id'] == extension_first_con_data_series['app_order_id'], 'order_cnt'].iloc[0]
            if not extension_repay_con_df.empty:
                extension_first_repay_con_hour_diff = (datetime.strptime(extension_repay_con_df.iloc[0]['settlement_time'], "%Y-%m-%d %H:%M:%S") - self.order_apply_time_datetime).total_seconds() / 3600
            else:
                extension_first_repay_con_hour_diff = float('nan')
            extension_first_con_loan_num = contract_data_df_sort.loc[contract_data_df_sort['activation_time'] > extension_first_con_data_series['activation_time'], 'app_order_id'].nunique()
            extension_first_con_repay_num = contract_data_df_sort.loc[(contract_data_df_sort['activation_time'] > extension_first_con_data_series['activation_time']) & (contract_data_df_sort['status'] == 6), 'app_order_id'].nunique()

            # 上一笔 展期合同
            extension_last_con_data_df = extension_con_data_df.tail(1)
            extension_last_con_isext = 1 if contract_data_df_sort.iloc[-1]['app_order_id'] in extension_order_statis_df['app_order_id'] else 0
            extension_last_con_rank = extension_last_con_data_df.index[0] + 1
            extension_last_con_data_series = extension_last_con_data_df.iloc[0]
            extension_last_con_hour_diff = (datetime.strptime(extension_last_con_data_series['activation_time'], "%Y-%m-%d %H:%M:%S") - self.order_apply_time_datetime).total_seconds() / 3600
            extension_last_con_data_isrepay = 1 if extension_last_con_data_series['settlement_time'] else 0
            extension_last_con_data_ext_cnt = extension_order_statis_df.loc[extension_order_statis_df['app_order_id'] == extension_last_con_data_series['app_order_id'], 'order_cnt'].iloc[0]
            if not extension_repay_con_df.empty:
                extension_last_repay_con_hour_diff = (datetime.strptime(extension_repay_con_df.iloc[-1]['settlement_time'], "%Y-%m-%d %H:%M:%S") - self.order_apply_time_datetime).total_seconds() / 3600
            else:
                extension_last_repay_con_hour_diff = float('nan')
            extension_last_con_loan_num = contract_data_df_sort.loc[contract_data_df_sort['activation_time'] > extension_last_con_data_series['activation_time'], 'app_order_id'].nunique()
            extension_last_con_repay_num = contract_data_df_sort.loc[(contract_data_df_sort['activation_time'] > extension_last_con_data_series['activation_time']) & (contract_data_df_sort['status'] == 6), 'app_order_id'].nunique()
        else:
            extension_first_con_rank = float('nan')
            extension_first_con_hour_diff = float('nan')
            extension_first_con_data_isrepay = float('nan')
            extension_first_con_data_ext_cnt = float('nan')
            extension_first_repay_con_hour_diff = float('nan')
            extension_first_con_loan_num = float('nan')
            extension_first_con_repay_num = float('nan')
            extension_last_con_isext = float('nan')
            extension_last_con_rank = float('nan')
            extension_last_con_hour_diff = float('nan')
            extension_last_con_data_isrepay = float('nan')
            extension_last_con_data_ext_cnt = float('nan')
            extension_last_repay_con_hour_diff = float('nan')
            extension_last_con_loan_num = float('nan')
            extension_last_con_repay_num = float('nan')

        feature_dict[f'extension_order_num_{suffix}'] = extension_order_num
        feature_dict[f'extension_extorder_num_{suffix}'] = extension_extorder_num
        feature_dict[f'extension_repay_con_num_{suffix}'] = extension_repay_con_num
        feature_dict[f'extension_first_con_rank_{suffix}'] = extension_first_con_rank
        feature_dict[f'extension_first_con_hour_diff_{suffix}'] = extension_first_con_hour_diff
        feature_dict[f'extension_first_con_data_isrepay_{suffix}'] = extension_first_con_data_isrepay
        feature_dict[f'extension_first_con_data_ext_cnt_{suffix}'] = extension_first_con_data_ext_cnt
        feature_dict[f'extension_first_repay_con_hour_diff_{suffix}'] = extension_first_repay_con_hour_diff
        feature_dict[f'extension_first_con_loan_num_{suffix}'] = extension_first_con_loan_num
        feature_dict[f'extension_first_con_repay_num_{suffix}'] = extension_first_con_repay_num
        feature_dict[f'extension_last_con_isext_{suffix}'] = extension_last_con_isext
        feature_dict[f'extension_last_con_rank_{suffix}'] = extension_last_con_rank
        feature_dict[f'extension_last_con_hour_diff_{suffix}'] = extension_last_con_hour_diff
        feature_dict[f'extension_last_con_data_isrepay_{suffix}'] = extension_last_con_data_isrepay
        feature_dict[f'extension_last_con_data_ext_cnt_{suffix}'] = extension_last_con_data_ext_cnt
        feature_dict[f'extension_last_repay_con_hour_diff_{suffix}'] = extension_last_repay_con_hour_diff
        feature_dict[f'extension_last_con_loan_num_{suffix}'] = extension_last_con_loan_num
        feature_dict[f'extension_last_con_repay_num_{suffix}'] = extension_last_con_repay_num
